home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part1 / 2230 < prev    next >
Encoding:
Internet Message Format  |  1996-08-06  |  33.0 KB

  1. Path: sun.soe.clarkson.edu!cline
  2. From: cline@sun.soe.clarkson.edu (Marshall Cline)
  3. Newsgroups: comp.lang.c++
  4. Subject: C++ FAQ: posting #3/4
  5. Followup-To: comp.lang.c++
  6. Date: 16 Jan 1996 16:38:47 GMT
  7. Organization: Paradigm Shift, Inc (OO consulting/training)
  8. Sender: cline@sun.soe.clarkson.edu
  9. Distribution: world
  10. Expires: +1 month
  11. Message-ID: <4dgkan$rls@library.erc.clarkson.edu>
  12. Reply-To: cline@parashift.com (Marshall Cline)
  13. NNTP-Posting-Host: sun.soe.clarkson.edu
  14. Summary: Please read this before posting to comp.lang.c++
  15.  
  16. comp.lang.c++ Frequently Asked Questions list (with answers, fortunately).
  17. Copyright (C) 1991-95 Marshall P. Cline, Ph.D.
  18. Posting 3 of 4.
  19. Posting #1 explains copying permissions, (no)warranty, table-of-contents, etc
  20.  
  21. ==============================================================================
  22. SECTION 14: Style guidelines
  23. ==============================================================================
  24.  
  25. Q81: What are some good C++ coding standards?
  26.  
  27. Thank you for reading this answer rather than just trying to set your own
  28. coding standards.
  29.  
  30. But please don't ask this question on comp.lang.c++.  Nearly every software
  31. engineer has, at some point, felt that coding standards are or can be used as a
  32. "power play."  Furthermore some attempts to set C++ coding standards have been
  33. made by those unfamiliar with the language and/or paradigm, so the standards
  34. end up being based on what WAS the state-of-the-art when the standards setters
  35. where writing code.  Such impositions generate an attitude of mistrust for
  36. coding standards.
  37.  
  38. Obviously anyone who asks this question on comp.lang.c++ wants to be trained so
  39. they DON'T run off on their own ignorance, but nonetheless the answers tend to
  40. generate more heat than light.
  41.  
  42. ==============================================================================
  43.  
  44. Q82: Are coding standards necessary?  Are they sufficient?
  45.  
  46. Coding standards do not make non OO programmers into OO programmers; only
  47. training and experience do that.  If coding standards have merit, it is that
  48. they discourage the petty fragmentation that occurs when large organizations
  49. coordinate the activities of diverse groups of programmers.
  50.  
  51. But you really want more than a coding standard.  The structure provided by
  52. coding standards gives neophytes one less degree of freedom to worry about,
  53. however pragmatics go well beyond pretty-printing standards.  Organizations
  54. need a consistent PHILOSOPHY of design and implementation.  E.g., strong or
  55. weak typing?  references or ptrs in interfaces?  stream I/O or stdio?  should
  56. C++ code call our C?  vise versa?  how should ABCs be used?  should inheritance
  57. be used as an implementation technique or as a specification technique?  what
  58. testing strategy should be employed?  inspection strategy?  should interfaces
  59. uniformly have a "get" and/or "set" method for each data member?  should
  60. interfaces be designed from the outside-in or the inside-out?  should errors be
  61. handled by try/catch/throw or return codes?  etc.
  62.  
  63. What is needed is a "pseudo standard" for detailed DESIGN.  I recommend a
  64. three-pronged approach to achieving this standardization: training, mentoring,
  65. and libraries.  Training provides "intense instruction," mentoring allows OO to
  66. be caught rather than just taught, and a high quality C++ class library
  67. provides "long term instruction."  There is a thriving commercial market for
  68. all three kinds of "training."  Advice by organizations who have been through
  69. the mill is consistent: Buy, Don't Build.  Buy libraries, buy training, buy
  70. tools, buy consulting.  Companies who have attempted to become a self-taught
  71. tool-shop as well as an application/system shop have found success difficult.
  72.  
  73. Few argue that coding standards are "ideal," or even "good," however they are
  74. necessary in the kind of organizations/situations described above.
  75.  
  76. The following FAQs provide some basic guidance in conventions and styles.
  77.  
  78. ==============================================================================
  79.  
  80. Q83: Should our organization determine coding standards from our C
  81.    experience?
  82.  
  83. No!
  84.  
  85. No matter how vast your C experience, no matter how advanced your C expertise,
  86. being a good C programmer does not make you a good C++ programmer.  Converting
  87. from C to C++ is more than just learning the syntax and semantics of the "++"
  88. part of C++.  Organizations who want the promise of OOP, but who fail to put
  89. the "OO" into OOP, are fooling themselves; the balance sheet will show their
  90. folly.
  91.  
  92. C++ coding standards should be tempered by C++ experts.  Asking comp.lang.c++
  93. is a start (but don't use the term "coding standard" in the question; instead
  94. simply say, "what are the pros and cons of this technique?").  Seek out experts
  95. who can help guide you away from pitfalls.  Get training.  Buy libraries and
  96. see if "good" libraries pass your coding standards.  Do NOT set standards by
  97. yourself unless you have considerable experience in C++.  Having no standard is
  98. better than having a bad standard, since improper "official" positions "harden"
  99. bad brain traces.  There is a thriving market for both C++ training and
  100. libraries from which to pool expertise.
  101.  
  102. One more thing: whenever something is in demand, the potential for charlatans
  103. increases.  Look before you leap.  Also ask for student-reviews from past
  104. companies, since not even expertise makes someone a good communicator.
  105. Finally, select a practitioner who can teach, not a full time teacher who has a
  106. passing knowledge of the language/paradigm.
  107.  
  108. ==============================================================================
  109.  
  110. Q84: Should I declare locals in the middle of a fn or at the top?
  111.  
  112. Declare near first use.
  113.  
  114. An object is initialized (constructed) the moment it is declared.  If you don't
  115. have enough information to initialize an object until half way down the fn, you
  116. can either initialize it to an "empty" value at the top then "assign" it later,
  117. or initialize it correctly half way down the fn.  It's cheaper (in runtime
  118. performance) to get it right the first time than to build it once, tear it
  119. down, and build it again.  Simple examples show a factor of 350% speed hit for
  120. simple classes like "String".  Your mileage may vary; surely the overall system
  121. degradation will be less that 300+%, but there WILL be degradation.
  122. UNNECESSARY degradation.
  123.  
  124. A common retort to the above is: "we"ll provide "set" methods for every datum
  125. in our objects, so the cost of construction will be spread out."  This is worse
  126. than the performance overhead, since now you're introducing a maintenance
  127. nightmare.  Providing "set" methods for every datum is tantamount to public
  128. data: you've exposed your implementation technique to the world.  The only
  129. thing you've hidden is the physical NAMES of your member objects, but the fact
  130. that you're using a List and a String and a float (for example) is open for all
  131. to see.  Maintenance generally consumes far more resources than run-time CPU.
  132.  
  133. Locals should be declared near their first use.  Sorry that this isn't familiar
  134. to C experts, but "new" doesn't necessarily mean "bad."
  135.  
  136. ==============================================================================
  137.  
  138. Q85: What source-file-name convention is best? "foo.C"? "foo.cc"? "foo.cpp"?
  139.  
  140. If you already have a convention, use it.  If not, consult your compiler to see
  141. what the compiler expects.  Typical answers are: ".C", ".cc", ".cpp", or
  142. ".cxx" (naturally the ".C" extension assumes a case-sensitive file system to
  143. distinguish ".C" from ".c").
  144.  
  145. At Paradigm Shift, Inc., we use ".C" in our Makefiles even on case-insensitive
  146. file systems (on case-insensitive file systems, we supply the compiler option
  147. that means "assume all .c files are C++ source files"; e.g., "-Tdp" for IBM
  148. CSet++, "-cpp" for Zortech C++, "-P" for Borland C++, etc).
  149.  
  150. ==============================================================================
  151.  
  152. Q86: What header-file-name convention is best? "foo.H"? "foo.hh"? "foo.hpp"?
  153.  
  154. If you already have a convention, use it.  If not, and if you don't need your
  155. editor to distinguish between C and C++ files, simply use ".h".  Otherwise use
  156. whatever the editor wants, such as ".H", ".hh", or ".hpp".
  157.  
  158. At Paradigm Shift, Inc., we use ".h" for both C and C++ source files (then
  159. again, we don't create many straight C header files).
  160.  
  161. ==============================================================================
  162.  
  163. Q87: Are there any lint-like guidelines for C++?
  164.  
  165. Yes, there are some practices which are generally considered dangerous.
  166. However none of these are universally "bad," since situations arise when
  167. even the worst of these is needed:
  168.  * a class "Fred"s assignment operator should return "*this" as an "Fred&"
  169.    (allows chaining of assignments)
  170.  * a class with any virtual fns ought to have a virtual destructor
  171.  * a class with any of {destructor, assignment operator, copy constructor}
  172.    generally needs all 3
  173.  * a class "Fred"s copy constructor and assignment operator should have "const"
  174.    in the parameter: respectively "Fred::Fred(const Fred&)" and
  175.    "Fred& Fred::operator=(const Fred&)".
  176.  * always use initialization lists for class sub-objects rather than assignment
  177.    the performance difference for user-defined classes can be substantial (3x!)
  178.  * many assignment operators should start by testing if "we" are "them"; e.g.,
  179.     Fred& Fred::operator= (const Fred& fred)
  180.     {
  181.       if (this == &fred) return *this;
  182.       //...normal assignment duties...
  183.       return *this;
  184.     }
  185.    sometimes there is no need to check, but these situations generally
  186.    correspond to when there's no need for an explicit user-specified assignment
  187.    op (as opposed to a compiler-synthesized assignment-op).
  188.  * in classes that define both "+=," "+" and "=," "a+=b" and "a=a+b" should
  189.    generally do the same thing; ditto for the other identities of builtin types
  190.    (e.g., a+=1 and ++a; p[i] and *(p+i); etc).  This can be enforced by writing
  191.    the binary ops using the "op=" forms; e.g.,
  192.     Fred operator+ (const Fred& a, const Fred& b)
  193.     {
  194.       Fred ans = a;
  195.       ans += b;
  196.       return ans;
  197.     }
  198.    This way the "constructive" binary ops don't even need to be friends.  But
  199.    it is sometimes possible to more efficiently implement common ops (e.g., if
  200.    class "Fred" is actually "String," and "+=" has to reallocate/copy string
  201.    memory, it may be better to know the eventual length from the beginning).
  202.  
  203. ==============================================================================
  204. SECTION 15: Keys for Smalltalk programmers to learn C++
  205. ==============================================================================
  206.  
  207. Q88: Why does C++'s FAQ have a section on Smalltalk? Is this
  208.    Smalltalk-bashing?
  209.  
  210. The two "major" OOPLs in the world are C++ and Smalltalk.  Due to its
  211. popularity as the OOPL with the second largest user pool, many new C++
  212. programmers come from a Smalltalk background.  This section answers the
  213. questions:
  214.  * what's different about the two languages
  215.  * what must a Smalltalk-turned-C++ programmer know to master C++
  216.  
  217. This section does *!*NOT*!* attempt to answer the questions:
  218.  * which language is "better"?
  219.  * why is Smalltalk "bad"?
  220.  * why is C++ "bad"?
  221.  
  222. Nor is it an open invitation for some Smalltalk terrorist to slash my tires
  223. while I sleep (on those rare occasions when I have time to rest these days :-).
  224.  
  225. ==============================================================================
  226.  
  227. Q89: What's the difference between C++ and Smalltalk?
  228.  
  229. The most important differences are:
  230.  
  231.  * static typing vs dynamic typing?
  232.  * must inheritance be used for subtyping only?
  233.  * value vs reference semantics?
  234.  
  235. The first two differences are illuminated in the remainder of this section; the
  236. third point is the subject of the section that follows.
  237.  
  238. If you're a Smalltalk programmer who wants to learn C++, you'd be very wise to
  239. study the next three FAQs carefully.
  240.  
  241. ==============================================================================
  242.  
  243. Q90: What is "static typing", and how is it similar/dissimilar to Smalltalk?
  244.  
  245. Static typing says the compiler checks the type-safety of every operation
  246. STATICALLY (at compile-time), rather than to generate code which will check
  247. things at run-time.  For example, with static typing, the signature matching of
  248. fn arguments is checked, and an improper match is flagged as an error by the
  249. COMPILER, not at run-time.
  250.  
  251. In OO code, the most common "typing mismatch" is invoking a member function
  252. against an object which isn't prepared to handle the operation.  E.g., if class
  253. "Fred" has member fn "f()" but not "g()", and "fred" is an instance of class
  254. "Fred", then "fred.f()" is legal and "fred.g()" is illegal.  C++ (statically
  255. typed) catches the error at compile time, and Smalltalk (dynamically typed)
  256. catches the error at run-time.  (Technically speaking, C++ is like Pascal
  257. --PSEUDO statically typed-- since ptr casts and unions can be used to violate
  258. the typing system; which reminds me: only use ptr casts and unions as often as
  259. you use "goto"s).
  260.  
  261. ==============================================================================
  262.  
  263. Q91: Which is a better fit for C++: "static typing" or "dynamic typing"?
  264.  
  265. If you want to use C++ most effectively, use it as a statically typed language.
  266.  
  267. C++ is flexible enough that you can (via ptr casts, unions, and #defines) make
  268. it "look" like Smalltalk.  But don't.  Which reminds me: try to avoid #define.
  269.  
  270. There are places where ptr casts and unions are necessary and even wholesome,
  271. but they should be used carefully and sparingly.  A ptr cast tells the compiler
  272. to believe you.  An incorrect ptr cast might corrupt your heap, scribble into
  273. memory owned by other objects, call nonexistent methods, and cause general
  274. failures.  It's not a pretty sight.  If you avoid these and related constructs,
  275. you can make your C++ code both safer and faster, since anything that can be
  276. checked at compile time is something that doesn't have to be done at run-time.
  277.  
  278. Even if you're in love with dynamic typing, please avoid it in C++, or else
  279. please consider using another language that better supports your desire to
  280. defer typing decisions to run-time.  C++ performs 100% of its type checking at
  281. compile time; it has NO built-in mechanism to do ANY type checking at run-time.
  282. If you use C++ as a dynamically typed OOPL, your life is in your own hands.
  283.  
  284. ==============================================================================
  285.  
  286. Q92: How can you tell if you have a dynamically typed C++ class library?
  287.  
  288. Hint #1: when everything is derived from a single root class, usually "Object."
  289. Hint #2: when the container classes (List, Stack, Set, etc) are non-templates.
  290. Hint #3: when the container classes (List, Stack, Set, etc) insert/extract
  291. elements as pointers to "Object" (you can put an Apple into such a container,
  292. but when you get it out, the compiler knows only that it is derived from
  293. Object, so you have to use a pointer cast to convert it back to an Apple*; and
  294. you better pray a lot that it really IS an Apple, cause your blood is on your
  295. own head).
  296.  
  297. You can make the pointer cast "safe" by using "dynamic_cast" (added to the
  298. language in 1994), but this dynamic testing is just that: dynamic.  This
  299. coding style is the essence of dynamic typing in C++.  You call a function
  300. that says "convert this Object into an Apple or give me NULL if its not an
  301. Apple," and you've got dynamic typing: you don't know what will happen until
  302. run-time.
  303.  
  304. When you use with templates to implement your containers, the C++ compiler can
  305. statically validate 99% of an application's typing information (the figure
  306. "99%" is apocryphal; some claim they always get 100%, those who need
  307. persistence get something less than 100% static type checking).  The point is:
  308. C++ gets genericity from templates, not from inheritance.
  309.  
  310. ==============================================================================
  311.  
  312. Q93: How do you use inheritance in C++, and is that different from Smalltalk?
  313.  
  314. Some people believe that the purpose of inheritance is code reuse.  In C++,
  315. this is wrong.  Stated plainly, "inheritance is not 'for' code reuse."
  316.  
  317. The purpose of inheritance in C++ is to express interface compliance
  318. (subtyping), not to get code reuse.  In C++, code reuse usually comes via
  319. composition rather than via inheritance.  In other words, inheritance is mainly
  320. a specification technique rather than an implementation technique.
  321.  
  322. This is a major difference with Smalltalk, where there is only one form of
  323. inheritance (C++ provides "private" inheritance to mean "share the code but
  324. don't conform to the interface", and "public" inheritance to mean "kind-of").
  325. The Smalltalk language proper (as opposed to coding practice) allows you to
  326. have the EFFECT of "hiding" an inherited method by providing an override that
  327. calls the "does not understand" method.  Furthermore Smalltalk allows a
  328. conceptual "is-a" relationship to exist APART from the subclassing hierarchy
  329. (subtypes don't have to be subclasses; e.g., you can make something that is-a
  330. Stack yet doesn't inherit from class Stack).
  331.  
  332. In contrast, C++ is more restrictive about inheritance: there's no way to make
  333. a "conceptual is-a" relationship without using inheritance (the C++ work-around
  334. is to separate interface from implementation via ABCs).  The C++ compiler
  335. exploits the added semantic information associated with public inheritance to
  336. provide static typing.
  337.  
  338. ==============================================================================
  339.  
  340. Q94: What are the practical consequences of diffs in Smalltalk/C++
  341.    inheritance?
  342.  
  343. Smalltalk lets you make a subtype that isn't a subclass, and allows you to make
  344. a subclass that isn't a subtype.  This allows Smalltalk programmers to be very
  345. carefree in putting data (bits, representation, data structure) into a class
  346. (e.g., you might put a linked list into a Stack class).  After all, if someone
  347. wants an array-based-Stack, they don't have to inherit from Stack; they could
  348. inherit such a class from Array if desired, even though an ArrayBasedStack is
  349. NOT a kind-of Array!
  350.  
  351. In C++, you can't be nearly as carefree.  Only mechanism (method code), but not
  352. representation (data bits) can be overridden in subclasses.  Therefore you're
  353. usually better off NOT putting the data structure in a class.  This leads to a
  354. stronger reliance on Abstract Base Classes (ABCs).
  355.  
  356. I like to think of the difference between an ATV and a Maseratti.  An ATV (all
  357. terrain vehicle) is more fun, since you can "play around" by driving through
  358. fields, streams, sidewalks, and the like.  A Maseratti, on the other hand, gets
  359. you there faster, but it forces you to stay on the road.  My advice to C++
  360. programmers is simple: stay on the road.  Even if you're one of those people
  361. who like the "expressive freedom" to drive through the bushes, don't do it in
  362. C++; it's not a good fit.
  363.  
  364. ==============================================================================
  365.  
  366. Q95: Do you need to learn a "pure" OOPL before you learn C++?
  367.  
  368. No (in fact, doing so might actually hurt you).
  369.  
  370. (Note that Smalltalk is a "pure" OOPL, and C++ is a "hybrid" OOPL).  Before
  371. reading this, please read the previous FAQs on the difference between C++ and
  372. Smalltalk.
  373.  
  374. The "purity" of the OOPL doesn't make the transition to C++ any easier.  In
  375. fact, the typical use of dynamic typing and non-subtyping inheritance can make
  376. it even harder for Smalltalk programmers to learn C++.  Paradigm Shift, Inc.,
  377. has taught OO technology to literally thousands of people, and we have noticed
  378. that people who want to learn C++ from a Smalltalk background usually have just
  379. as hard a time as those who've never seen inheritance before.  In fact, those
  380. with extensive experience with a dynamically typed OOPL (usually but not always
  381. Smalltalk) might even have a HARDER time, since it's harder to UNLEARN habits
  382. than it is to learn the statically typed way from the beginning.
  383.  
  384. ==============================================================================
  385.  
  386. Q96: What is the NIHCL?  Where can I get it?
  387.  
  388. NIHCL stands for "national-institute-of-health's-class-library."
  389. it can be acquired via anonymous ftp from [128.231.128.7]
  390. in the file pub/NIHCL/nihcl-3.0.tar.Z
  391.  
  392. NIHCL (some people pronounce it "N-I-H-C-L," others pronounce it like "nickel")
  393. is a C++ translation of the Smalltalk class library.  There are some ways where
  394. NIHCL's use of dynamic typing helps (e.g., persistent objects).  There are also
  395. places where its use of dynamic typing creates tension with the static typing
  396. of the C++ language.
  397.  
  398. See previous FAQs on Smalltalk for more.
  399.  
  400. ==============================================================================
  401. SECTION 16: Reference and value semantics
  402. ==============================================================================
  403.  
  404. Q97: What is value and/or reference semantics, and which is best in C++?
  405.  
  406. With reference semantics, assignment is a pointer-copy (i.e., a REFERENCE).
  407. Value (or "copy") semantics mean assignment copies the value, not just the
  408. pointer.  C++ gives you the choice: use the assignment operator to copy the
  409. value (copy/value semantics), or use a ptr-copy to copy a pointer (reference
  410. semantics).  C++ allows you to override the assignment operator to do anything
  411. your heart desires, however the default (and most common) choice is to copy the
  412. VALUE.
  413.  
  414. Pros of reference semantics: flexibility and dynamic binding (you get dynamic
  415. binding in C++ only when you pass by ptr or pass by ref, not when you pass by
  416. value).
  417.  
  418. Pros of value semantics: speed.  "Speed" seems like an odd benefit to for a
  419. feature that requires an object (vs a ptr) to be copied, but the fact of the
  420. matter is that one usually accesses an object more than one copies the object,
  421. so the cost of the occasional copies is (usually) more than offset by the
  422. benefit of having an actual object rather than a ptr to an object.
  423.  
  424. There are three cases when you have an actual object as opposed to a pointer to
  425. an object: local vars, global/static vars, and fully contained member objects
  426. in a class.  The most important of these is the last ("composition").
  427.  
  428. More info about copy-vs-reference semantics is given in the next FAQs.  Please
  429. read them all to get a balanced perspective.  The first few have intentionally
  430. been slanted toward value semantics, so if you only read the first few of the
  431. following FAQs, you'll get a warped perspective.
  432.  
  433. Assignment has other issues (e.g., shallow vs deep copy) which are not covered
  434. here.
  435.  
  436. ==============================================================================
  437.  
  438. Q98: What is "virtual data," and how-can / why-would I use it in C++?
  439.  
  440. Virtual data allows a derived class to change the exact class of a base class's
  441. member object.  Virtual data isn't strictly "supported" by C++, however it
  442. can be simulated in C++.  It ain't pretty, but it works.
  443.  
  444. To simulate virtual data in C++, the base class must have a pointer to the
  445. member object, and the derived class must provide a "new" object to be pointed
  446. to by the base class's pointer.  The base class would also have one or more
  447. normal constructors that provide their own referrent (again via "new"), and the
  448. base class's destructor would "delete" the referent.
  449.  
  450. For example, class "Stack" might have an Array member object (using a pointer),
  451. and derived class "StretchableStack" might override the base class member data
  452. from "Array" to "StretchableArray".  For this to work, StretchableArray would
  453. have to inherit from Array, so Stack would have an "Array*".  Stack's normal
  454. constructors would initialize this "Array*" with a "new Array", but Stack would
  455. also have a (possibly "protected:") constructor that would accept an "Array*"
  456. from a derived class.  StretchableArray's constructor would provide a "new
  457. StretchableArray" to this special constructor.
  458.  
  459. Pros:
  460.  * Easier implementation of StretchableStack (most of the code is inherited).
  461.  * Users can pass a StretchableStack as a kind-of Stack.
  462.  
  463. Cons:
  464.  * Adds an extra layer of indirection to access the Array.
  465.  * Adds some extra freestore allocation overhead (both new and delete).
  466.  * Adds some extra dynamic binding overhead (reason given in next FAQ).
  467.  
  468. In other words, we succeeded at making OUR job easier as the implementor of
  469. StretchableStack, but all our users pay for it.  Unfortunately the extra
  470. overhead was imposed on both users of StretchableStack AND on users of Stack.
  471.  
  472. See the FAQ after the next to find out how much the users "pay."  Also: PLEASE
  473. read the few FAQs that follow the next one too (YOU WILL NOT GET A BALANCED
  474. PERSPECTIVE WITHOUT THE OTHERS).
  475.  
  476. ==============================================================================
  477.  
  478. Q99: What's the difference between virtual data and dynamic data?
  479.  
  480. The easiest way to see the distinction is by an analogy with "virtual fns":
  481. A virtual member fn means the declaration (signature) must stay the same in
  482. subclasses, but the defn (body) can be overridden.  The overriddenness of an
  483. inherited member fn is a static property of the subclass; it doesn't change
  484. dynamically throughout the life of any particular object, nor is it possible
  485. for distinct objects of the subclass to have distinct defns of the member fn.
  486.  
  487. Now go back and re-read the previous paragraph, but make these substitutions:
  488.  * "member fn" --> "member object"
  489.  * "signature" --> "type"
  490.  * "body"      --> "exact class'
  491. After this, you'll have a working definition of virtual data.
  492.  
  493. Another way to look at this is to distinguish "per-object" member functions
  494. from "dynamic" member functions.  A "per-object" member fn is a member fn that
  495. is potentially different in any given instance of an object, and could be
  496. implemented by burying a function ptr in the object; this pointer could be
  497. "const", since the pointer will never be changed throughout the object's life.
  498. A "dynamic" member fn is a member fn that will change dynamically over time;
  499. this could also be implemented by a function ptr, but the fn ptr would not be
  500. const.
  501.  
  502. Extending the analogy, this gives us three distinct concepts for data members:
  503.  * virtual data: the defn ("class") of the member object is overridable in
  504.    subclasses provided its declaration ("type") remains the same, and this
  505.    overriddenness is a static property of the subclass.
  506.  * per-object-data: any given object of a class can instantiate a different
  507.    conformal (same type) member object upon initialization (usually a "wrapper"
  508.    object), and the exact class of the member object is a static property of
  509.    the object that wraps it.
  510.  * dynamic-data: the member object's exact class can change dynamically over
  511.    time.
  512.  
  513. The reason they all look so much the same is that none of this is "supported"
  514. in C++.  It's all merely "allowed," and in this case, the mechanism for faking
  515. each of these is the same: a ptr to a (probably abstract) base class.  In a
  516. language that made these "first class" abstraction mechanisms, the difference
  517. would be more striking, since they'd each have a different syntactic variant.
  518.  
  519. ==============================================================================
  520.  
  521. Q100: Should I normally use pointers to freestore allocated objects for my
  522.    data members, or should I use "composition"?
  523.  
  524. Composition.
  525.  
  526. Your member objects should normally be "contained" in the composite object (but
  527. not always; "wrapper" objects are a good example of where you want a ptr/ref;
  528. also the N-to-1-uses-a relationship needs something like a ptr/ref).
  529.  
  530. There are three reasons why fully contained member objects ("composition") has
  531. better performance than ptrs to freestore-allocated member objects:
  532.  
  533.  * Extra layer to indirection every time you need to access the member object.
  534.  * Extra freestore allocations ("new" in constructor, "delete" in destructor).
  535.  * Extra dynamic binding (reason given below).
  536.  
  537. ==============================================================================
  538.  
  539. Q101: What are relative costs of the 3 performance hits associated with
  540.    allocating member objects from the freestore?
  541.  
  542. The three performance hits are enumerated in the previous FAQ:
  543.  * By itself, an extra layer of indirection is small potatoes.
  544.  * Freestore allocations can be a performance issue (the performance of the
  545.    typical implementation of malloc degrades when there are many allocations;
  546.    OO s/w can easily become "freestore bound" unless you're careful).
  547.  * The extra dynamic binding comes from having a ptr rather than an object.
  548.    Whenever the C++ compiler can know an object's EXACT class, virtual fn
  549.    calls can be STATICALLY bound, which allows inlining.  Inlining allows
  550.    zillions (would you believe half a dozen :-) optimization opportunities
  551.    such as procedural integration, register lifetime issues, etc.  The C++
  552.    compiler can know an object's exact class in three circumstances: local
  553.    variables, global/static variables, and fully-contained member objects.
  554.  
  555. Thus fully-contained member objects allow significant optimizations that
  556. wouldn't be possible under the "member objects-by-ptr" approach.  This is the
  557. main reason that languages which enforce reference-semantics have "inherent"
  558. performance challenges.
  559.  
  560. NOTE: PLEASE READ THE NEXT THREE FAQs TO GET A BALANCED PERSPECTIVE!
  561.  
  562. ==============================================================================
  563.  
  564. Q102: Are "inline virtual" member fns ever actually "inlined"?
  565.  
  566. Yes but...
  567.  
  568. A virtual call via a ptr or ref is always resolved dynamically, which can never
  569. be inlined.  Reason: the compiler can't know which actual code to call until
  570. run-time (i.e., dynamically), since the code may be from a derived class that
  571. was created after the caller was compiled.
  572.  
  573. Therefore the only time an inline virtual call can be inlined is when the
  574. compiler knows the "exact class" of the object which is the target of the
  575. virtual function call.  This can happen only when the compiler has an actual
  576. object rather than a pointer or reference to an object.  I.e., either with a
  577. local object, a global/static object, or a fully contained object inside a
  578. composite.
  579.  
  580. Note that the difference between inlining and non-inlining is normally MUCH
  581. more significant than the difference between a regular fn call and a virtual fn
  582. call.  For example, the difference between a regular fn call and a virtual fn
  583. call is often just two extra memory references, but the difference between an
  584. inline function and a non-inline function can be as much as an order of
  585. magnitude (for zillions of calls to insignificant member fns, loss of inlining
  586. virtual fns can result in 25X speed degradation!  [Doug Lea, "Customization in
  587. C++," proc Usenix C++ 1990]).
  588.  
  589. A practical consequence of this insight: don't get bogged down in the endless
  590. debates (or sales tactics!) of compiler/language vendors who compare the cost
  591. of a virtual function call on their language/compiler with the same on another
  592. language/compiler.  Such comparisons are largely meaningless when compared with
  593. the ability of the language/compiler to "inline expand" member function calls.
  594. I.e., many language implementation vendors make a big stink about how good
  595. their dispatch strategy is, but if these implementations don't INLINE method
  596. calls, the overall system performance would be poor, since it is inlining --NOT
  597. dispatching-- that has the greatest performance impact.
  598.  
  599. NOTE: PLEASE READ THE NEXT TWO FAQs TO SEE THE OTHER SIDE OF THIS COIN!
  600.  
  601. ==============================================================================
  602.  
  603. Q103: Sounds like I should never use reference semantics, right?
  604.  
  605. Wrong.
  606.  
  607. Reference semantics are A Good Thing.  We can't live without pointers.  We just
  608. don't want our s/w to be One Gigantic Rats Nest Of Pointers.  In C++, you can
  609. pick and choose where you want reference semantics (ptrs/refs) and where you'd
  610. like value semantics (where objects physically contain other objects etc).  In
  611. a large system, there should be a balance.  However if you implement absolutely
  612. EVERYTHING as a pointer, you'll get enormous speed hits.
  613.  
  614. Objects near the problem skin are larger than higher level objects.  The
  615. IDENTITY of these "problem space" abstractions is usually more important than
  616. their "value."  Thus reference semantics should be used for problem-space
  617. objects.
  618.  
  619. Note that these problem space objects are normally at a higher level of
  620. abstraction than the solution space objects, so the problem space objects
  621. normally have a relatively lower frequency of interaction.  Therefore C++ gives
  622. us an IDEAL situation: we choose reference semantics for objects that need
  623. unique identity or that are too large to copy, and we can choose value
  624. semantics for the others.  Thus the highest frequency objects will end up with
  625. value semantics, since we install flexibility where it doesn't hurt us (only),
  626. and we install performance where we need it most!
  627.  
  628. These are some of the many issues the come into play with real OO design.
  629. OO/C++ mastery takes time and high quality training.  If you want a powerful
  630. tool, you've got to invest.
  631.  
  632.            <<<<DON'T STOP NOW!  READ THE NEXT FAQ TOO!!>>>>
  633.  
  634. ==============================================================================
  635.  
  636. Q104: Does the poor performance of ref semantics mean I should pass-by-value?
  637.  
  638. Nope.
  639.  
  640. The previous FAQ were talking about MEMBER OBJECTS, not parameters.  Generally,
  641. objects that are part of an inheritance hierarchy should be passed by ref or by
  642. ptr, NOT by value, since only then do you get the (desired) dynamic binding
  643. (pass-by-value doesn't mix with inheritance, since larger subclass objects get
  644. "sliced" when passed by value as a base class object).
  645.  
  646. Unless compelling reasons are given to the contrary, member objects should be
  647. by value and parameters should be by reference.  The discussion in the previous
  648. few FAQs indicates some of the "compelling reasons" for when member objects
  649. should be by reference.
  650.  
  651. --
  652. Paradigm Shift, Inc. / P.O. Box 5108 / Potsdam, NY  13676
  653. Voice: 315-353-6100 / FAX: 315-353-6110
  654.